#ifndef SINGLETON_H
#define SINGLETON_H

#include <iostream>
#include <map>
#include <string>

class Wall{
public:
  virtual void Print() = 0;
};

class CastleWall : public Wall {
public:
  CastleWall() {
    std::cout << "CastleWall" << std::endl;
  }
  void Print() {
    std::cout << "CastleWall Print" << std::endl;
  }
};

class SchoolWall : public Wall {
public:
  SchoolWall() {
    std::cout << "SchoolWall" << std::endl;
  }
  void Print() {
    std::cout << "SchoolWall Print" << std::endl;
  }
};

class Singleton {
public:
  static Singleton* Instance();
  static void Register(const std::string& name, Wall* wall);
  static Wall* Lookup(const std::string& name);
private:
  Singleton() {}
private:
  static Singleton* instance_;
  static std::map<std::string, Wall*> context_;
};

Singleton* _instance = nullptr;
std::map<std::string, Wall*> Singleton::context_;


Singleton* Singleton::Instance() {
  if (_instance == nullptr) {
    _instance = new Singleton();
  }

  return _instance;
}
void Singleton::Register(const std::string& name, Wall* wall) {
  context_[name] = wall;
}

Wall* Singleton::Lookup(const std::string& name) {
  return (context_.find(name) != context_.end()) ? context_[name] : nullptr;
}

#endif // SINGLETON_H
